package im_server

import (
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"go.uber.org/zap"
	"pim/pkg/codes"
	"pim/pkg/models"
	"pim/pkg/tools"
	"sync"
)

func (s *server) HttpGetWsWebGateway(ctx *gin.Context) {
	logger := s.logger

	// 身份校验通过
	// 将设备添加到 全局变量

	ws, err := s.wsUpGrader.Upgrade(ctx.Writer, ctx.Request, nil)
	if err != nil {
		s.logger.Debug("upgrade:", zap.Error(err))
		return
	}

	// 直接升级

	// 第一个包是读取 token

	tokeninfo, err := GetTokenStringByWs(logger, ws)

	if err != nil {
		return
	}

	client := &ClientConn{
		ctx:         ctx,
		Conn:        ws,
		UserID:      tokeninfo.UserID,
		Pf:          int(tokeninfo.Pf),
		w:           new(sync.Mutex),
		logger:      logger,
		svr:         s,
		cacheUserID: make(map[int64]bool),
		cacheChatID: make(map[int64]*models.WsClientChatInfoCache),
	}
	streamID := tools.OperationIDGenerator()

	client.SetCloseHandler(func(code int, text string) error {
		// 收到关闭时间
		logger.Info("Close Callback ", zap.Int("code", code), zap.String("txt", text))
		if !client.IsClose {
			client.IsClose = true
		}
		return nil
	})

	defer func() {

		// 关闭所有未完成的任务
		client.CloseEvent()

		s.RemoveConn(client, streamID)
		_ = ws.Close()
	}()

	// 完成 关系映射
	s.AddNewConn(client, streamID)
	// 读写进程

	client.DoInitUserContext()

	for true {
		select {
		case <-ctx.Done():
			logger.Info("Client 断开", zap.Int64("uid", tokeninfo.UserID), zap.Int("pf", client.Pf))
			return
		default:
		}

		// 读取数据包

		bt, msg, err := client.ReadMessage()

		if err != nil {
			logger.Debug("读取数据包失败", zap.Int64("uid", tokeninfo.UserID), zap.Int("pf", client.Pf))
			return
		}

		logger.Debug("info", zap.Int("type", bt), zap.ByteString("msg", msg))
		// TODO 处理业务

		//client.WriteMessage(websocket.BinaryMessage)

		client.ProcMessage(msg)

	}
}

func GetTokenStringByWs(logger *zap.Logger, ws *websocket.Conn) (token *tools.TokenClaims, err error) {
	_, fristPackege, err := ws.ReadMessage()
	if err != nil {
		return
	}

	token, err = tools.ParseToken(string(fristPackege))

	if err != nil {
		pack := tools.NewProtocolPackage(codes.EventMod, codes.EventModConnectFail, 0, nil)

		output := pack.Bytes()

		ws.WriteMessage(websocket.BinaryMessage, output)
		return
	}

	// 成功 返回链接成功事件

	//uniqueID := tools.OperationIDGenerator()

	pack := tools.NewProtocolPackage(codes.EventMod, codes.EventModConnectSuccess, 0, nil)

	output := pack.Bytes()

	ws.WriteMessage(websocket.BinaryMessage, output)

	return
}

func (s *server) HttpGetWsGateway(ctx *gin.Context) {

	tokeninfo, err := tools.CheckHttpToken(ctx)
	if err != nil {
		return
	}

	logger := s.logger

	// 身份校验通过
	// 将设备添加到 全局变量

	ws, err := s.wsUpGrader.Upgrade(ctx.Writer, ctx.Request, nil)
	if err != nil {
		s.logger.Debug("upgrade:", zap.Error(err))
		return
	}

	client := &ClientConn{
		ctx:                ctx,
		Conn:               ws,
		UserID:             tokeninfo.UserID,
		Pf:                 int(tokeninfo.Pf),
		w:                  new(sync.Mutex),
		logger:             logger,
		svr:                s,
		cacheUserID:        make(map[int64]bool),
		cacheChatID:        make(map[int64]*models.WsClientChatInfoCache),
		cacheUploadFileMap: make(map[int64]*FileTaskInfo),
	}
	streamID := tools.OperationIDGenerator()

	client.SetCloseHandler(func(code int, text string) error {
		// 收到关闭时间
		logger.Info("Close Callback ", zap.Int("code", code), zap.String("txt", text))
		if !client.IsClose {
			client.IsClose = true
		}
		return nil
	})

	defer func() {

		s.RemoveConn(client, streamID)
		_ = ws.Close()
	}()

	// 完成 关系映射
	s.AddNewConn(client, streamID)
	// 读写进程

	for true {
		select {
		case <-ctx.Done():
			logger.Info("Client 断开", zap.Int64("uid", tokeninfo.UserID), zap.Int("pf", client.Pf))
			return
		default:
		}

		// 读取数据包

		bt, msg, err := client.ReadMessage()

		if err != nil {
			logger.Debug("读取数据包失败", zap.Int64("uid", tokeninfo.UserID), zap.Int("pf", client.Pf))
			return
		}

		logger.Debug("info", zap.Int("type", bt), zap.ByteString("msg", msg))
		// TODO 处理业务

		//client.WriteMessage(websocket.BinaryMessage)

		client.ProcMessage(msg)

	}

}
